package com.kapcb.mvc.listener;

import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.RestController;

import java.util.Set;

/**
 * <a>Title: ReportServiceProxy </a>
 * <a>Author: cb <a>
 * <a>Description: 报告服务代理 <a>
 *
 * @author cb
 * @version 1.0
 * @date 2024/4/22 6:46 PM
 * @since 1.0
 */
@Slf4j
public class ReportServiceProxy implements BeanPostProcessor, ApplicationListener<ContextRefreshedEvent> {

    /**
     * 标志：防止重复调用
     */
    private boolean executed = false;

    /**
     * 服务实例集合
     */
    private final Set<Object> serviceInstances = Sets.newHashSet();

    /**
     * Spring IOC 容器初始化刷新时，ContextRefreshedEvent 事件会被发布
     * 也可以在 ConfigurationApplicationContext 接口中使用 refresh 方法来触发事件发布
     * 此处的初始化是指：Spring IOC 容器中所有的 Bean 被成功装载，后置增强 Bean 处理被检测并激活
     * 所有的单例 Bean 被预实例化，ApplicationContext 容器已就绪可用
     *
     * @param event ContextRefreshedEvent
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 判断是否已经处理过，初始化时处理一次即可，避免重复处理
        if (executed) {
            return;
        }

        executed = true;
        if (log.isDebugEnabled()) {
            log.debug("ReportServiceProxy.onApplicationEvent");
        }

        for (Object restControllerBean : serviceInstances) {
            if (restControllerBean == null) {
                continue;
            }

            RestController restController = AnnotationUtils.findAnnotation(restControllerBean.getClass(), RestController.class);
            if (restController == null) {
                continue;
            }

            // todo 根据方法上的注解，分析并提取需要提交上报的服务信息
        }
        // todo 提交服务上报操作
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 收集 IOC 容器中所有的 RestController 注解修饰的类
        if (bean.getClass().isAnnotationPresent(RestController.class)) {
            if (log.isDebugEnabled()) {
                log.debug("ReportServiceProxy.postProcessAfterInitialization --> {}", bean.getClass().getSimpleName());
            }
            this.serviceInstances.add(bean);
        }
        return bean;
    }

}
